//
//  CSMapRootViewController.swift
//  Cycling
//
//  Created by CSS on 3/31/23.
//

import UIKit

import MapboxCoreNavigation
import MapboxNavigation
import MapboxDirections
import Turf

class CSMapRootViewController: BaseViewController {
    
    lazy private var navContentView: UIView = {
        let navContentView: UIView = .forAutoLayout()
        navContentView.backgroundColor = .white
        return navContentView
    }()
    
    lazy private var searchBgView: UIView = {
        let contentView: UIView = .forAutoLayout()
        contentView.backgroundColor = .clear
        
        contentView.layer.borderColor = UIColor.color(withHexString: "#EEEEEE").cgColor
        contentView.layer.borderWidth = 1
        contentView.layer.cornerRadius = 4
        
        let searchIconView = UIImageView(image: UIImage(named: "sousuo"))
        searchIconView.translatesAutoresizingMaskIntoConstraints = false
        let searchLbl: UILabel = .forAutoLayout()
        searchLbl.text = "搜索"
        searchLbl.textColor = .color(withHexString: "#B3B3B3")
        searchLbl.font = .systemFont(ofSize: 18)
        
        let searchButton = UIButton(type: .custom)
        searchButton.translatesAutoresizingMaskIntoConstraints = false
        searchButton.backgroundColor = .clear
        searchButton.addTarget(self, action: #selector(searchButtonAction(_:)), for: .touchUpInside)
        
        contentView.addSubviews([searchIconView, searchLbl, searchButton])
        
        searchButton.pinTo(parentView: contentView)
        
        let constraints = [
            searchIconView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 10),
            searchIconView.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
            searchLbl.leadingAnchor.constraint(equalTo: searchIconView.trailingAnchor, constant: 8),
            searchLbl.centerYAnchor.constraint(equalTo: contentView.centerYAnchor),
        ]
        NSLayoutConstraint.activate(constraints)
        
        return contentView
    }()
    
    lazy private var searchView: CSMapSearchListView = {
        let searchView: CSMapSearchListView = .forAutoLayout(hidden: true)
        searchView.searchListViewBlock = { [weak self]type, item in
            guard let self = self else {
                return
            }
            if type == .clear {
                self.clearHistory()
            } else if type == .goToSelectRoute {
                guard let location = item as? CLLocationCoordinate2D else {
                    return
                }
                self.goToMapRouteSelectVC(withDestinationLocation: location)
            }
        }
        return searchView
    }()
    
    lazy private var mapView: NavigationMapView = {
        let mapView: NavigationMapView = .forAutoLayout(frame: view.bounds)
        
        mapView.userLocationStyle = .puck2D()
        
        let navigationViewportDataSource = NavigationViewportDataSource(mapView.mapView, viewportDataSourceType: .raw)
        navigationViewportDataSource.options.followingCameraOptions.zoomUpdatesAllowed = false
        navigationViewportDataSource.followingMobileCamera.zoom = 15.0
        mapView.navigationCamera.viewportDataSource = navigationViewportDataSource
        
//        mapView.setCenter(.init(latitude: 77.018178, longitude: 116.306745), zoomLevel: 15, animated: true)
//        mapView.showsUserLocation = true
//        mapView.userTrackingMode = .follow
//        mapView.isPitchEnabled = true
//        mapView.isRotateEnabled = false
//        mapView.showsScale = true
        
//        mapView.delegate = self
        
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapGestureReceived(_:)))
        mapView.addGestureRecognizer(tapGesture)
        
        return mapView
    }()
    lazy private var mapFunctionContentStack: UIStackView = {
        let stackView: UIStackView = .forAutoLayout()
        stackView.axis = .vertical
        return stackView
    }()
    lazy private var mapScaleContentView: UIView = {
        let contentView: UIView = .forAutoLayout()
        contentView.backgroundColor = .white
        contentView.layer.cornerRadius = 17
        
        contentView.layer.shadowColor = UIColor.color(withHexString: "#0AD39F").withAlphaComponent(0.3).cgColor
        contentView.layer.shadowOffset = .zero
        contentView.layer.shadowOpacity = 1
        contentView.layer.shadowRadius = 6
        
        return contentView
    }()
    lazy private var scaleBigButton = scaleButton(withType: 0)
    lazy private var scaleSmallButton = scaleButton(withType: 1)
    
    lazy private var routeSelectContentView: UIView = .forAutoLayout(hidden: true)
    lazy private var routeSelectMaskView: UIView = .forAutoLayout(hidden: true)
    private var routeSelectView: CSRouteSelectView?
    
    // MARK: 中间变量
    private var componentViews: [UIView] {
        [navContentView, mapView, mapFunctionContentStack, searchView]
    }
    private var hotRoutes: [(MGLLineStyleLayer, MGLShapeSource)] = []
    private var mapStyleDidLoad = false
    private var anyShape: MGLShape?
    
    var startPoint: CLLocationCoordinate2D? {
        mapView.mapView.location.latestLocation?.coordinate
    }
    var endPoint: CLLocationCoordinate2D?

    override func viewDidLoad() {
        super.viewDidLoad()
        
        setupViews()
        makeConstraints()
        
        loadData()
    }

}

// MARK: MGLMapView委托处理类
extension CSMapRootViewController: MGLMapViewDelegate {
    
    func mapView(_ mapView: MGLMapView, didUpdate userLocation: MGLUserLocation?) {
        
    }
    
    func mapViewDidFinishLoadingMap(_ mapView: MGLMapView) {
        mapView.setUserTrackingMode(.none, animated: true) {
            
        }
    }
    
    func mapViewDidFailLoadingMap(_ mapView: MGLMapView, withError error: Error) {
        mapView.setUserTrackingMode(.none, animated: true) {
            
        }
    }
    
    func mapView(_ mapView: MGLMapView, didFinishLoading style: MGLStyle) {
        mapStyleDidLoad = true
        addHotRoutes()
    }
    
}

// MARK: 事件处理类
private extension CSMapRootViewController {
    
    @objc func searchButtonAction(_ sender: Any) {
        searchView.isHidden = false
        let _ = searchView.becomeFirstResponder()
    }
    
    @objc func scaleBigAction(_ sender: Any) {
//        mapView.setZoomLevel(mapView.zoomLevel * 1.1, animated: true)
    }
    
    @objc func scaleSmallAction(_ sender: Any) {
//        mapView.setZoomLevel(mapView.zoomLevel * 0.9, animated: true)
    }
    
}

// MARK: 工具类方法
private extension CSMapRootViewController {
    
    func setupViews() {
        view.addSubviews(componentViews)
        
        navContentView.addSubview(searchBgView)
        mapFunctionContentStack.addArrangedSubview(mapScaleContentView)
        
        mapScaleContentView.addSubviews([scaleBigButton, scaleSmallButton])
    }
    
    func makeConstraints() {
        
        let mapFunctionConstraints = [
            scaleBigButton.leadingAnchor.constraint(equalTo: mapScaleContentView.leadingAnchor),
            scaleBigButton.trailingAnchor.constraint(equalTo: mapScaleContentView.trailingAnchor),
            scaleBigButton.topAnchor.constraint(equalTo: mapScaleContentView.topAnchor),
            
            scaleBigButton.bottomAnchor.constraint(equalTo: scaleSmallButton.topAnchor),
            
            scaleSmallButton.leadingAnchor.constraint(equalTo: mapScaleContentView.leadingAnchor),
            scaleSmallButton.trailingAnchor.constraint(equalTo: mapScaleContentView.trailingAnchor),
            scaleSmallButton.bottomAnchor.constraint(equalTo: mapScaleContentView.bottomAnchor)
        ]
        
        let constraints = [
            
            navContentView.topAnchor.constraint(equalTo: view.topAnchor),
            navContentView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            navContentView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            navContentView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 44),
            
            mapView.topAnchor.constraint(equalTo: navContentView.bottomAnchor),
            mapView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            mapView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            mapView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            
            searchBgView.leadingAnchor.constraint(equalTo: navContentView.leadingAnchor, constant: 18),
            searchBgView.centerXAnchor.constraint(equalTo: navContentView.centerXAnchor),
            searchBgView.heightAnchor.constraint(equalToConstant: 30),
            searchBgView.bottomAnchor.constraint(equalTo: navContentView.bottomAnchor, constant: -7),
            
            searchView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            searchView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            searchView.topAnchor.constraint(equalTo: view.safeTopAnchor),
            searchView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            
            mapFunctionContentStack.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -18),
            mapFunctionContentStack.centerYAnchor.constraint(equalTo: view.centerYAnchor)
        ] + mapFunctionConstraints
        
        NSLayoutConstraint.activate(constraints)
    }
    
    func mapHotRouteLayer(withData routeData: Data) -> (MGLLineStyleLayer, MGLShapeSource)? {
        
        guard let shape = try? MGLShape(data: routeData, encoding: String.Encoding.utf8.rawValue) else {
            return nil
        }
        anyShape = shape
        let source = MGLShapeSource(identifier: "1234", shape: shape)
        let layer = MGLLineStyleLayer(identifier: "1234", source: source)
        layer.lineColor = .init(forConstantValue: UIColor.red)
        layer.lineWidth = .init(forConstantValue: 10)
        layer.lineGapWidth = .init(forConstantValue: 10)
        return (layer, source)
        
    }
    
}

// MARK: 工具类方法(UI处理类)
private extension CSMapRootViewController {
    
    func scaleButton(withType type: Int) -> UIButton {
        let button: UIButton = .init(type: .custom)
        button.backgroundColor = .clear
        button.translatesAutoresizingMaskIntoConstraints = false
        button.adjustsImageWhenDisabled = false
        button.adjustsImageWhenHighlighted = false
        if type == 0 {
            button.setImage(UIImage(named: "map_scale_big"), for: .normal)
            button.addTarget(self, action: #selector(scaleBigAction(_:)), for: .touchUpInside)
        } else {
            button.setImage(UIImage(named: "map_scale_small"), for: .normal)
            button.addTarget(self, action: #selector(scaleSmallAction(_:)), for: .touchUpInside)
        }
        button.contentEdgeInsets = .init(top: 14, left: 14, bottom: 14, right: 14)
        
        return button
    }
    
}

// MARK: 工具类方法(数据处理)
private extension CSMapRootViewController {
    
    func loadData() {
        loadTestData()
    }
    
    func loadTestData() {
        removeHotRoutes()
        
        guard let testPath = Bundle.main.url(forResource: "GeoJSONSourceExample", withExtension: "geojson") else {
            return
        }
        
        guard let testData = try? Data(contentsOf: testPath) else {
            return
        }
        
        guard let testLayer = mapHotRouteLayer(withData: testData) else {
            return
        }
        
        hotRoutes.append(testLayer)
        
        addHotRoutes()
    }
    
    func removeHotRoutes() {
        //移除之前已有的
//        hotRoutes.forEach {
//            mapView.style?.removeLayer($0.0)
//            mapView.style?.removeSource($0.1)
//        }
    }
    
    func addHotRoutes() {
        if !mapStyleDidLoad {
            return
        }
        if hotRoutes.count == 0 {
            return
        }
        
//        hotRoutes.forEach({
//            mapView.style?.addLayer($0.0)
//            mapView.style?.addSource($0.1)
//        })
        
//        mapView.setUserTrackingMode(.none, animated: true) { [weak self] in
//            guard let self = self else {
//                return
//            }
//            self.mapView.setCamera(self.mapView.cameraThatFitsShape(self.anyShape!, direction: 0, edgePadding: .zero), animated: true)
//        }
    }
    
}

// MARK: 工具类方法(地图操作)
private extension CSMapRootViewController {
    
    @objc func tapGestureReceived(_ tapGesture: UITapGestureRecognizer) {
        /*
        let locationPoint = tapGesture.location(in: mapView)
        let location = mapView.convert(locationPoint, toCoordinateFrom: mapView)
        
        endPoint = location
        
        removeCustomAnnotation()
        
//        requestCycleRoutes()
        if routeSelectViewHasShown {
            hideRouteSelectView()
        } else {
            mapView.addAnnotation(CSMapAnimationModel(coordinator: location))
            showOrReloadRouteSelectView()
        }
         */
    }
    
    func requestCycleRoutes() {
        guard let startPoint = startPoint, let endPoint = endPoint else {
            return
        }
        let routesVC = YQMapRoutesViewController()
        routesVC.setupLocations(withFromLocation: startPoint, endLocation: endPoint)
        navigationController?.pushViewController(routesVC, animated: true)
    }
    
    func removeCustomAnnotation() {
        /*
        mapView.annotations?.forEach({
            if $0 is CSMapAnimationModel {
                mapView.removeAnnotation($0)
            }
        })
         */
    }
    
}

// MARK: Search页面处理
private extension CSMapRootViewController {
    
    func clearHistory() {
        showAlert(withTitle: "您确定要清空搜索历史吗？", leftTitle: "取消", rightTitle: "确认", rightStyle: .destructive) {
            
        }
    }
    
}

// MARK: 选择路线处理
private extension CSMapRootViewController {
    
    var routeSelectViewHasShown: Bool {
        routeSelectView != nil && routeSelectView!.superview != nil
    }
    
    func showOrReloadRouteSelectView() {
        guard let startPoint = startPoint, let endPoint = endPoint else {
            return
        }
        
        if let routeSelectView = routeSelectView, routeSelectView.superview != nil {
            routeSelectView.reload(withStartPoint: startPoint, toPoint: endPoint)
            return
        }
        
        if routeSelectContentView.superview == nil {
            routeSelectView?.backgroundColor = .white
            routeSelectContentView.addSubview(routeSelectMaskView)
            parent?.view.addSubview(routeSelectContentView)
            routeSelectContentView.backgroundColor = .clear
            NSLayoutConstraint.activate([
                routeSelectContentView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
                routeSelectContentView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
                routeSelectContentView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
                
                routeSelectMaskView.leadingAnchor.constraint(equalTo: routeSelectContentView.leadingAnchor),
                routeSelectMaskView.trailingAnchor.constraint(equalTo: routeSelectContentView.trailingAnchor),
                routeSelectMaskView.bottomAnchor.constraint(equalTo: routeSelectContentView.bottomAnchor),
                routeSelectMaskView.topAnchor.constraint(equalTo: routeSelectContentView.safeBottomAnchor)
            ])
        }
        routeSelectMaskView.isHidden = true
        routeSelectContentView.isHidden = true
        
        let routeSelectView: CSRouteSelectView = .forAutoLayout(hidden: true)
        routeSelectView.reload(withStartPoint: startPoint, toPoint: endPoint)
        routeSelectView.goNavigationBlock = { [weak self] in
            self?.goToNavigation(withRoute: $0, routeOptions: $1)
        }
        routeSelectContentView.addSubview(routeSelectView)
        self.routeSelectView = routeSelectView
        
        NSLayoutConstraint.activate([
            routeSelectView.leadingAnchor.constraint(equalTo: routeSelectContentView.leadingAnchor),
            routeSelectView.trailingAnchor.constraint(equalTo: routeSelectContentView.trailingAnchor),
            routeSelectView.topAnchor.constraint(equalTo: routeSelectContentView.topAnchor),
            routeSelectView.bottomAnchor.constraint(equalTo: routeSelectContentView.safeBottomAnchor),
        ])
        
        routeSelectContentView.layoutIfNeeded()
        routeSelectView.transform = .init(translationX: 0, y: routeSelectView.frame.height)
        routeSelectMaskView.isHidden = false
        routeSelectContentView.isHidden = false
        routeSelectView.isHidden = false
        
        
        UIView.animate(withDuration: 0.3) {
            routeSelectView.transform = .identity
        }
        
    }
    
    func hideRouteSelectView(_ animate: Bool = true) {
        guard let routeSelectView = routeSelectView, routeSelectView.superview != nil else {
            return
        }
        if !animate {
            routeSelectView.removeFromSuperview()
            routeSelectContentView.isHidden = true
            return
        }
        UIView.animate(withDuration: 0.3) {
            routeSelectView.transform = .init(translationX: 0, y: routeSelectView.frame.height)
        } completion: { [weak self]success in
            guard let self = self else {
                return
            }
            routeSelectView.removeFromSuperview()
            self.routeSelectContentView.isHidden = true
        }

    }
    
    func goToNavigation(withRoute route: IndexedRouteResponse, routeOptions: RouteOptions?) {
        
//        let mainRoute = MGLPointCollectionFeature(coordinates: route.shape!.coordinates, count: UInt(route.shape!.coordinates.count))
//        let mainRoute = MGLPolylineFeature(route.shape!)
        
//        let waypoints: [Waypoint] = Array(route.currentRoute!.legs.dropLast().compactMap({ $0.destination }))
//
//        var features = [Turf.Feature]()
//        for (waypointIndex, waypoint) in waypoints.enumerated() {
//            var feature = Feature(geometry: .point(Point(waypoint.coordinate)))
//            feature.properties = [
//                "waypointCompleted": .boolean(waypointIndex < 0),
//                "name": .number(Double(waypointIndex + 1)),
//            ]
//            features.append(feature)
//        }
//        
//        let shape = FeatureCollection(features: features)
//        
//        if let data = shape.geoJSONData(usingEncoding: String.Encoding.utf8.rawValue) {
//            let dataString = String(data: data, encoding: .utf8)
//            print("dataString: \(String(describing: dataString))")
//        }
        
//        guard let routeOptions = routeOptions else {
//            return
//        }
        let navigationService = MapboxNavigationService(indexedRouteResponse: route, credentials: NavigationSettings.shared.directions.credentials, simulating: .always)
        
        let topBannerVC = CSNavigationTopBannerViewController()
        let bottomBannerView = CSNavigationBottomBannerViewController()
        
        topBannerVC.topActionBlock = { [weak self] type in
            guard let self = self else {
                return
            }
            if type == 0 {
                navigationService.endNavigation()
                self.presentedViewController?.dismiss(animated: true)
            }
        }
        
        bottomBannerView.bannerActionTypeBlock = { [weak self]type in
            if type == 0 {
                self?.presentedViewController?.dismiss(animated: true)
            }
        }
//        bottomBannerView.navigationService = navigationService
        
        let navigationOptions = NavigationOptions(navigationService: navigationService, voiceController: .init(navigationService: navigationService, speechSynthesizer: SystemSpeechSynthesizer()), topBanner: topBannerVC, bottomBanner: bottomBannerView)
        let navigationVC = NavigationViewController(for: route, navigationOptions: navigationOptions)
        
//        navigationVC.mapView?.routeCasingColor = .color(withHexString: "#0FDAB2")
//        navigationVC.mapView?.trafficUnknownColor = .color(withHexString: "#0FDAB2")
//        navigationVC.mapView?.traversedRouteColor = .color(withHexString: "#808080")
        navigationVC.routeLineTracksTraversal = true
                
        navigationVC.modalPresentationStyle = .fullScreen
        present(navigationVC, animated: true)
        
        hideRouteSelectView()
        removeCustomAnnotation()
    }
    
    func goToMapRouteSelectVC(withDestinationLocation location: CLLocationCoordinate2D) {
        guard let startPoint = startPoint else {
            return
        }
        let mapRouteSelectVC = YQMapRoutesViewController()
        mapRouteSelectVC.fromLocation = startPoint
        mapRouteSelectVC.endLocation = location
        navigationController?.pushViewController(mapRouteSelectVC, animated: true)
    }
    
}
